using System;
using System.Collections.Generic;
using System.Text;

namespace Generic.DataStructures.Trees
{
    public class TreeNodeCollection<T> : IList<TreeNode<T>>
    {


        internal TreeNodeCollection(Tree<T> tree, TreeNode<T> parentNode)
        {
            _tree = tree;
            _parentNode = parentNode;
            _innerList = new ListWithEvents<TreeNode<T>>();
            _innerList.AfterAdd +=new ListAddHandler<TreeNode<T>>(_innerList_AfterAdd);
            _innerList.AfterInsert +=new ListInsertHandler<TreeNode<T>>(_innerList_AfterInsert);
            _innerList.AfterRemove += new ListRemoveHandler<TreeNode<T>>(_innerList_AfterRemove);
            _innerList.AfterSet += new ListSetHandler<TreeNode<T>>(_innerList_AfterSet);
        }

        void _innerList_AfterSet(object sender, ListSetEventArgs<TreeNode<T>> e)
        {
            e.NewValue.ParentNode = _parentNode;
            e.NewValue.Tree = _tree;
        }

        void _innerList_AfterRemove(object sender, ListRemoveEventArgs<TreeNode<T>> e)
        {
            TreeNode<T> parentNode = e.Value.ParentNode;
            foreach (TreeNode<T> child in e.Value.Children)
            {
                child.ParentNode = parentNode;
            }
        }

        void _innerList_AfterInsert(object sender, ListInsertEventArgs<TreeNode<T>> e)
        {
            e.Value.ParentNode = _parentNode;
            e.Value.Tree = _tree;

        }

        void _innerList_AfterAdd(object sender, ListAddEventArgs<TreeNode<T>> e)
        {
            e.Value.ParentNode = _parentNode;
            e.Value.Tree = _tree;
        }

        public TreeNode<T> Add(T nodeValue)
        {
            TreeNode<T> node = new TreeNode<T>(_tree, nodeValue);
            Add(node);
            return node;
        }

        public void Insert(int index, T nodeValue)
        {
            TreeNode<T> node = new TreeNode<T>(_tree, nodeValue);
            Insert(index, node);
        }

        private Tree<T> _tree;
        public Tree<T> Tree
        {
            get { return _tree; }
        }

        private TreeNode<T> _parentNode;
        public TreeNode<T> ParentNode
        {
            get { return _parentNode; }
        }

        ListWithEvents<TreeNode<T>> _innerList;
        protected ListWithEvents<TreeNode<T>> InnerList
        {
            get
            {
                return _innerList;
            }
            set
            {
                _innerList = value;
            }
        }

        #region IList<TreeNode<T>> Members

        public int IndexOf(TreeNode<T> item)
        {
            return InnerList.IndexOf(item);
        }

        public void Insert(int index, TreeNode<T> item)
        {
            InnerList.Insert(index, item);
        }

        public void RemoveAt(int index)
        {
            InnerList.RemoveAt(index);
        }

        public TreeNode<T> this[int index]
        {
            get
            {
                return InnerList[index];
            }
            set
            {
                InnerList[index] = value;
            }
        }

        #endregion

        #region ICollection<TreeNode<T>> Members

        public void Add(TreeNode<T> item)
        {
            InnerList.Add(item);
        }

        public void Clear()
        {
            InnerList.Clear();
        }

        public bool Contains(TreeNode<T> item)
        {
            return InnerList.Contains(item);
        }

        public void CopyTo(TreeNode<T>[] array, int arrayIndex)
        {
            InnerList.CopyTo(array, arrayIndex);
        }

        public int Count
        {
            get { return InnerList.Count; }
        }

        public bool IsReadOnly
        {
            get { return false; }
        }

        public bool Remove(TreeNode<T> item)
        {
            return InnerList.Remove(item);
        }

        #endregion

        #region IEnumerable<TreeNode<T>> Members

        public IEnumerator<TreeNode<T>> GetEnumerator()
        {
            return InnerList.GetEnumerator();
        }

        #endregion
        
        #region IEnumerable Members

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }

        #endregion
    }
}
